﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp
{
    // 读取模式枚举：提供不同的输出处理策略
    public enum ReadMode { Line, Char, SmartBuffer }
    // 完善的命令执行器（支持取消操作）
    public class CommandExecutor
    {
        private Process _process;
        private readonly object _lock = new object();
        private ReadMode _readMode;
        // 事件：用于向调用方反馈信息
        public event Action<string> OnOutputReceived; // 输出内容事件
        public event Action<int> OnCompleted; // 执行完成事件
        public event Action<Exception> OnErrorOccurred; // 错误发生事件

        // 缓冲区大小（可根据实际输出调整）
        private const int BufferThreshold = 10;
        // 进度更新的特征标记
        private const string ProgressMarker = "...";
        // 单词分隔符（用于辅助判断是否可以安全分割）
        private static readonly char[] WordSeparators = { ' ', ',', ';', '.', '!', '?', '\t' };

        public void Execute(string programPath, string arguments, string workingDirectory = null, Encoding encoding = null, ReadMode readMode = ReadMode.Char)
        {
            if (string.IsNullOrEmpty(programPath))
                throw new ArgumentNullException(nameof(programPath));

            if (!File.Exists(programPath))
                throw new FileNotFoundException("程序文件不存在", programPath);

            _readMode = readMode;
            if (encoding == null)
                encoding = Encoding.UTF8;

            var startInfo = new ProcessStartInfo
            {
                FileName = programPath,
                Arguments = arguments,
                WorkingDirectory = string.IsNullOrEmpty(workingDirectory) ? Environment.CurrentDirectory : workingDirectory,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                CreateNoWindow = true,
                StandardOutputEncoding = encoding,
                StandardErrorEncoding = encoding
            };

            try
            {
                lock (_lock)
                {
                    _process = new Process { StartInfo = startInfo };
                }
                // 使用队列控制顺序输出, 注释掉事件
                // _process.OutputDataReceived += OutputHandler;
                // _process.ErrorDataReceived += ErrorHandler;

                _process.Start();

                // 关键改进：使用同步读取而非异步，避免缓冲延迟
                // var outputTask = System.Threading.Tasks.Task.Run(() => ReadOutput(_process.StandardOutput, false));
                // var errorTask = System.Threading.Tasks.Task.Run(() => ReadOutput(_process.StandardError, true));

                // 使用线程安全队列确保输出顺序
                var outputQueue = new SynchronizedQueue<string>();
                var outputTask = System.Threading.Tasks.Task.Run(() => ReadStream(_process.StandardOutput, false, outputQueue));
                var errorTask = System.Threading.Tasks.Task.Run(() => ReadStream(_process.StandardError, true, outputQueue));
                // 启动队列处理任务，按顺序触发事件
                var processQueueTask = Task.Run(() => ProcessOutputQueue(outputQueue));

                // 等待所有输出处理完成
                Task.WaitAll(outputTask, errorTask);

                // 通知队列处理任务结束
                outputQueue.Enqueue(null);
                processQueueTask.Wait();

                _process.WaitForExit();
                OnCompleted?.Invoke(_process.ExitCode);
            }
            catch (Exception ex)
            {
                OnErrorOccurred?.Invoke(ex);
                throw;
            }
            finally
            {
                lock (_lock)
                {
                    if (_process != null)
                    {
                        _process.Dispose();
                        _process = null;
                    }
                }
            }
        }

        // 根据选择的模式读取流内容并放入队列
        private void ReadStream(StreamReader reader, bool isError, SynchronizedQueue<string> queue)
        {
            switch (_readMode)
            {
                case ReadMode.Line:
                    ReadLine(reader, isError, queue);
                    break;
                case ReadMode.Char:
                    ReadChar(reader, isError, queue);
                    break;
                case ReadMode.SmartBuffer:
                    ReadWithSmartBuffer(reader, isError, queue);
                    break;
            }
        }

        // 同步读取输出流（解决缓冲问题的核心）
        private void ReadOutput(StreamReader reader, bool isError)
        {
            // ReadLine(reader, isError);
            ReadChar(reader, isError);
            // ReadWithSmartBuffer(reader, isError);
        }

        private void ReadLine(StreamReader reader, bool isError)
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                OnOutputReceived?.Invoke(isError ? $"[警告] {line}" : $"[输出] {line}");
                // 强制刷新（对某些程序有效）
                reader.BaseStream.Flush();
            }
        }
        private void ReadChar(StreamReader reader, bool isError)
        {
            /*int charCode;
            // 逐字符读取（charCode为-1表示读取结束）
            while ((charCode = reader.Read()) != -1)
            {
                char c = (char)charCode;
                string data = c.ToString();
                OnOutputReceived?.Invoke(isError ? $"{data}" : $"{data}");
            }*/
            // 每次读取1个字符
            char[] buffer = new char[1];
            int bytesRead;

            while ((bytesRead = reader.Read(buffer, 0, 1)) > 0)
            {
                string data = new string(buffer, 0, bytesRead);
                OnOutputReceived?.Invoke(data);
            }
        }

        // 智能缓冲读取：优先保证文本完整性
        private void ReadWithSmartBuffer(StreamReader reader, bool isError)
        {
            var buffer = new StringBuilder();
            int charCode;

            while ((charCode = reader.Read()) != -1)
            {
                char c = (char)charCode;

                // 处理回车符（\r）：通常用于覆盖当前行（如进度更新）
                if (c == '\r')
                {
                    // 输出当前缓冲内容（模拟行覆盖前的内容）
                    if (buffer.Length > 0)
                    {
                        OnOutputReceived?.Invoke(isError ? $"[警告] {buffer}" : $"[输出] {buffer}");
                        buffer.Clear();
                    }
                    continue; // 跳过\r本身，避免输出混乱
                }

                buffer.Append(c);

                // 触发输出的条件（满足其一）：
                bool shouldFlush =
                    c == '\n' || // 换行符：完整行结束
                    buffer.ToString().Contains(ProgressMarker) || // 进度标记：需要实时反馈
                    (buffer.Length > 0 && WordSeparators.Contains(buffer[buffer.Length - 1])); // 单词分隔符：避免截断单词

                if (shouldFlush)
                {
                    string output = buffer.ToString();
                    OnOutputReceived?.Invoke(isError ? $"[警告] {output}" : $"[输出] {output}");
                    buffer.Clear();
                }
            }

            // 输出剩余内容
            if (buffer.Length > 0)
            {
                OnOutputReceived?.Invoke(isError ? $"[警告] {buffer}" : $"[输出] {buffer}");
            }
        }

        private void OutputHandler(object sender, DataReceivedEventArgs e)
        {
            if (!string.IsNullOrEmpty(e.Data))
                OnOutputReceived?.Invoke($"[输出] {e.Data}");
        }

        private void ErrorHandler(object sender, DataReceivedEventArgs e)
        {
            if (!string.IsNullOrEmpty(e.Data))
                OnOutputReceived?.Invoke($"[警告] {e.Data}");
        }

        public void Cancel()
        {
            lock (_lock)
            {
                if (_process != null && !_process.HasExited)
                {
                    try
                    {
                        _process.Kill();
                    }
                    catch (Exception ex)
                    {
                        OnErrorOccurred?.Invoke(new Exception("取消操作失败", ex));
                    }
                }
            }

        }
        // 处理输出队列，按顺序触发事件
        private void ProcessOutputQueue(SynchronizedQueue<string> queue)
        {
            while (true)
            {
                var message = queue.Dequeue();
                if (message == null) // 空消息表示结束
                    break;

                OnOutputReceived?.Invoke(message);
            }
        }

        // 按行读取模式
        private void ReadLine(StreamReader reader, bool isError, SynchronizedQueue<string> queue)
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                if (!string.IsNullOrEmpty(line))
                {
                    queue.Enqueue(isError ? $"[警告] {line}" : $"[输出] {line}");
                }
            }
        }

        // 按字符读取模式
        private void ReadChar(StreamReader reader, bool isError, SynchronizedQueue<string> queue)
        {
            char[] buffer = new char[1];
            int bytesRead;

            while ((bytesRead = reader.Read(buffer, 0, 1)) > 0)
            {
                string data = new string(buffer, 0, bytesRead);
                // queue.Enqueue(isError ? $"[警告] {data}" : $"[输出] {data}");
                queue.Enqueue(data);
            }
        }

        // 智能缓冲读取模式（平衡实时性和完整性）
        private void ReadWithSmartBuffer(StreamReader reader, bool isError, SynchronizedQueue<string> queue)
        {
            var buffer = new StringBuilder();
            int charCode;

            while ((charCode = reader.Read()) != -1)
            {
                char c = (char)charCode;

                // 处理回车符（\r）：通常用于覆盖当前行（如进度更新）
                if (c == '\r')
                {
                    if (buffer.Length > 0)
                    {
                        string output = buffer.ToString().TrimEnd('\r', '\n', ' ');
                        if (!string.IsNullOrEmpty(output))
                        {
                            queue.Enqueue(isError ? $"[警告] {output}" : $"[输出] {output}");
                        }
                        buffer.Clear();
                    }
                    continue;
                }

                buffer.Append(c);

                // 触发输出的条件（满足其一）
                bool shouldFlush =
                    c == '\n' || // 换行符：完整行结束
                    buffer.ToString().Contains(ProgressMarker) || // 进度标记：需要实时反馈
                    (buffer.Length > 0 && WordSeparators.Contains(buffer[buffer.Length - 1])); // 单词分隔符：避免截断单词

                if (shouldFlush)
                {
                    string output = buffer.ToString().TrimEnd('\r', '\n', ' ');
                    if (!string.IsNullOrEmpty(output))
                    {
                        queue.Enqueue(isError ? $"[警告] {output}" : $"[输出] {output}");
                    }
                    buffer.Clear();
                }
            }

            // 输出剩余内容
            if (buffer.Length > 0)
            {
                string output = buffer.ToString().TrimEnd('\r', '\n', ' ');
                if (!string.IsNullOrEmpty(output))
                {
                    queue.Enqueue(isError ? $"[警告] {output}" : $"[输出] {output}");
                }
            }
        }
    }

    // 线程安全的队列，用于保证输出顺序
    public class SynchronizedQueue<T>
    {
        private readonly Queue<T> _queue = new Queue<T>();
        private readonly AutoResetEvent _signal = new AutoResetEvent(false);
        private readonly object _queueLock = new object();

        /// <summary>
        /// 入队操作
        /// </summary>
        public void Enqueue(T item)
        {
            lock (_queueLock)
            {
                _queue.Enqueue(item);
            }
            _signal.Set(); // 通知有新元素
        }

        /// <summary>
        /// 出队操作（如果队列为空则阻塞等待）
        /// </summary>
        public T Dequeue()
        {
            while (true)
            {
                lock (_queueLock)
                {
                    if (_queue.Count > 0)
                    {
                        return _queue.Dequeue();
                    }
                }
                _signal.WaitOne(); // 等待新元素
            }
        }
    }
}
